<?php
/**
 * This is the file to define Database.
 * 
 * @author	Justin Yoo
 * @version	0.0.1.0001
 * @package	KYR.Core
 * 
 */

//	Checks if this file is called within the framework; otherwise terminates.
if (!defined("IS_FRAMEWORK") || !IS_FRAMEWORK)	header("Location: http://".$_SERVER["HTTP_HOST"]."/error/404");

/**
 * This is class Database that handles both MySQL and MS-SQL.
 *
 * Handles both MySQL and MS-SQL.
 * 
 * @author	Justin Yoo
 * @package	KYR.Core
 * 
 */
class Database
{
	private $_type		= null;
	private $_conn		= null;
	private $_result	= null;
	private $_mysqli	= null;
	
	/**
	 * Initiates the Database class.
	 *
	 * @access	public
	 * @param	string	$type	Type of DBMS.
	 * @exception				Throws and Exception while connecting the database.
	 *
	 */
	public function __construct($type = "MySQL")
	{
		//	Sets the DBMS type.
		$this->_type = $type;

		//	Sets the DB connection.
		try
		{
			$this->_ConnectDatabase();
		}
		catch (DatabaseException $ex) { throw $ex; }
	}

	/**
	 * Connects the database.
	 *
	 * @access	private
	 * @exception	Throws an Exception while connecting the database.
	 *
	 */
	private function _ConnectDatabase()
	{
		//	Determines the web site.
		$site	= null;
		if (in_array($_SERVER["HTTP_HOST"], explode("|", LIVE_SITES)))
			$site = "live";
		elseif (in_array($_SERVER["HTTP_HOST"], explode("|", TEST_SITES)))
			$site = "test";
		elseif (in_array($_SERVER["HTTP_HOST"], explode("|", DEV_SITES)))
			$site = "dev";
		else
			$site = "local";

		//	Gets the connection strings.
		Factory::parseConfig("db.config");
		$config = Factory::GetDb($site, $this->_type);
		//	Gets the databas connection.
		try
		{
			switch (strtolower($this->_type))
			{
				case "mysql":
					//	Gets the MySQLi object.
					$this->_mysqli = @new MySQLi($config["DataSource"], $config["UserID"], $config["Password"], $config["InitialCatalog"]);
					if (mysqli_connect_error())
						throw new DatabaseException("Database Connection failed");
					break;
				case "mssql":
					$this->_conn = @mssql_connect($config["DataSource"], $config["UserID"], $config["Password"]);
					if ($this->_conn)
						mssql_select_db($config["InitialCatalog"], $this->_conn);
					else
						throw new DatabaseException("Database Connection failed");
					break;
			}
		}
		catch (DatabaseException $ex) { throw $ex; }
	}

	/**
	 * Adds quotation marks to avoid SQL injection.
	 *
	 * @access	public
	 * @param	string	$value	Value to be quoted.
	 * @return	string			Returns the quoted value.
	 *
	 */
	public function Quote($value)
	{
		$value	= stripslashes($value);
		$value	= str_replace("'", "''", $value);
		$value	= str_replace("\0", "[NULL]", $value);
		$value	= utf8_decode($value);
		return $value;
	}
	
	/**
	 * Sends a database query.
	 *
	 * @access	public
	 * @param	string	$query	SQL query.
	 * @exception				Throws an Exception while processing a database query.
	 *
	 */
	public function Query($query)
	{
		//	Replaces the sing single quotation mark to double single one.
		$query	= str_replace("&#039;", "''", $query);
		//	Sends and returns the query.
		try
		{
			switch (strtolower($this->_type))
			{
				case "mysql":
					$this->_result = $this->_mysqli->query($query, MYSQLI_STORE_RESULT);
					if ($this->_mysqli->error)
						throw new DatabaseException("Database query failed");
					break;
				case "mssql":
					$this->_result = mssql_query($query, $this->_conn);
					break;
			}
			if (!$this->_result)
				throw new DatabaseException("Database query failed");
		}
		catch (DatabaseException $ex) { throw $ex; }
	}
	
	/**
	 * Fetches the query results.
	 *
	 * @access	public
	 * @return	array	Returns the associated array as a query result.
	 * @exception		Throws and Exception while fetching the query result.
	 *
	 */
	public function Fetch()
	{
		//	Returns the query result as an associated array format.
		$row = null;
		try
		{
			switch (strtolower($this->_type))
			{
				case "mysql":
					$row = $this->_result->fetch_assoc();
					//$row = mysql_fetch_assoc($this->_result);
					break;
				case "mssql":
					$row = mssql_fetch_assoc($this->_result);
					break;
			}
		}
		catch (DatabaseException $ex) { throw $ex; }
		//	Sets the empty result to FALSE.
		switch (strtolower($this->_type))
		{
			case "mysql":
				if (empty($row))
					$row = false;
				break;
			case "mssql":
				if (!$row)
					$row = false;
				break;
		}
		return $row;
	}
	
	/**
	 * Closes the database connection.
	 *
	 * @access	public
	 * @exception	Throws an Exception while closing the database connection.
	 *
	 */
	public function Close()
	{
		//	Closes the database connection.
		try
		{
			switch (strtolower($this->_type))
			{
				case "mysql":
					if ($this->_result)
						$this->_result->free();
					if (isset($this->_mysqli))
						$this->_mysqli->close();
					break;
				case "mssql":
					if (isset($this->_result))
						mssql_free_result($this->_result);
					if (isset($this->_conn))
						mssql_close($this->_conn);
					break;
			}
		}
		catch (DatabaseException $ex) { throw $ex; }
	}
	
	/**
	 * Destroys the Database class.
	 *
	 * @access	public
	 * @exception	Throws an Exception while destroying the Database class.
	 *
	 */
	public function __destruct()
	{
		try { $this->Close(); } catch (DatabaseException $ex) { throw $ex; }
	}
}
?>
